package com.ctu.gzero.elements
{
	import com.ctu.gzero.compose.Composer;
	import com.ctu.gzero.edit.ISelectionManager;
	
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;
	
	public class DOMElement extends EventDispatcher
	{
		[ArrayElementType("com.ctu.gzero.elements.ParaElement")]
		private var _paraList:ArrayCollection;
		private var _composer:Composer;
		private var _interactionManager:ISelectionManager
		private var _textLength:int = 0;
		private var _margin:Number = 5;
		public function DOMElement()
		{
			_paraList = new ArrayCollection();
		}
		
		public function get textLength():int
		{	
			return _textLength;	
		}
		
		public function set interactionManager(val:ISelectionManager):void
		{
			if(_interactionManager != val)
			{
				_interactionManager = val;
				if(val != null)
					_interactionManager.dom = this;

				_composer.interactionManagerChanged();
			}
		}
		
		public function get interactionManager():ISelectionManager
		{
			return _interactionManager;
		}
		
		public function set composer(val:Composer):void
		{
			_composer = val;
			_composer.dom = this;
		}
		
		public function get composer():Composer
		{
			return _composer;
		}
		
		public function get paraList():ArrayCollection
		{
			return _paraList;
		}
		
		public function set paraList(val:ArrayCollection):void
		{
			_paraList = val;
		}
		
		public function addPara(para:ParaElement):void
		{
			para.dom = this;
			_paraList.addItem(para);
		}
		
		public function getPara(idx:int):ParaElement
		{
			return _paraList.getItemAt(idx) as ParaElement;
		}
		
		public function firstDamagedPara():ParaElement
		{
			var para:ParaElement;
			for(var i:int=0; i<_paraList.length; i++)
			{
				para = _paraList.getItemAt(i) as ParaElement;
				if(para.firstInvalidTxLine())
				{
					break;
				}
			}
			return para;
		}
		
		public function removePara(idx:int):void
		{
			_paraList.removeItemAt(idx);
		}
		
		public function getParaIndex(para:ParaElement):int
		{
			return _paraList.getItemIndex(para);
		}
		
		public function findParaAtPosition(absolutePosition:int):ParaElement
		{
			var para:ParaElement;
			var paraIndex:int;
			var status:Boolean = false;
			var paraLength:int = paraList.length;
			
			for(var i:int=0; i<paraLength; i++)
			{
				if(absolutePosition >= getPara(i).absoluteStart && absolutePosition <= getPara(i).absoluteStart + getPara(i).textLength -1 )
				{
					paraIndex = i;
					status = true;
					break;
				}
			}
			
			if(status == false)
				throw new RangeError("DOMElement findParaAtPosition: given offset is out of range ");

			para = getPara(paraIndex);
			
			return para;
		}
		
		/**
		 * DOM 의 모든 element의 텍스트 흐름에 대한 값들을 다시 계산하여 세팅
		 */
		
		public function normalize():void
		{
			var _paraListLength:int = 0;			
			var offset:int = 0;
			
			_paraListLength = _paraList.length;
			
			for(var i:int=0; i<_paraListLength; i++)
			{
				var para:ParaElement = getPara(i);
				para.absoluteStart = offset;
				para.normalize();
				offset += para.textLength;
			}
			
			_textLength = offset;
		}
		
		public function get margin():Number
		{
			return _margin;
		}
		
		public function set margin(val:Number):void
		{
			_margin = val;
		}

	}
}